/*
 * Copyright (c) 2013 Michael Armbruster
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
using System;
using System.Collections.Generic;
using System.IO;

namespace MangafoxPDFGenerator
{
	/// <summary>
	/// Main class for our program.
	/// </summary>
	static class MainClass
	{
		/// <summary>
		/// The working directory of our program.
		/// </summary>
		private static string WorkingDirectory;

		/// <summary>
		/// The DPI used for all images we will process (we will make sure that
		/// all images use this DPI with the help of a call to the ImageMagick
		/// 'convert' command).
		/// </summary>
		private static string DPI;

		/// <summary>
		/// The entry point of the program, where the program control starts and ends.
		/// </summary>
		/// <param name='args'>
		/// The command-line arguments.
		/// </param>
		public static void Main (string[] args)
		{
			// Print our program head
			PrintHead ();

			// Parse all command-line arguments
			ParseArguments (args);

#if DEBUG
			// If we built the application in debug mode, we want to output the
			// path of our working directory
			Console.WriteLine ("[DEBUG: Working directory is \"" +
				WorkingDirectory + "\"]");
#endif

			// We will use our API to obtain all valid manga directories
			List<string> validDirectories = API.GetValidMangaDirectories (
				WorkingDirectory
			);

			// Iterate through all valid subdirectories to perform the real action
			foreach (string subdir in validDirectories) {
				// Get the properties of the Manga we will work on now
				Dictionary<string, string> manga = 
					API.GetPropertiesByHakuNekoFolderName (subdir);

				// Tell the user which Manga we will work on now
				Console.WriteLine ("Converting Episode " + manga ["episode"] +
					" - " + manga ["episodeName"] + " (Volume " +
				    manga ["volume"] + ")...");

				// First of all, get all jpg images in the current subdirectory
				string[] images = Directory.GetFiles (
					subdir,
					"*.jpg",
					SearchOption.TopDirectoryOnly
				);

				// Tell the user that we will convert all images to the same DPI
				Console.WriteLine ("Converting all images to " + DPI + " dpi...");

				// Iterate through all images in the current subdirectory
				foreach (string image in images) {
					// Set the DPI of every image to the given DPI since that is
					// usually a good value for creating our PDF files. The user
					// can change that with the command-line argument "-dpi=x"
					// where "x" is the dpi specifictaion itself as a number
					bool dpiSuccess = API.CallIMConvert (
						image,
						"-units PixelsPerInch",
						image,
						"-quality 100 -density " + DPI
					);

#if DEBUG
					// If we built the application in debug mode, we want to
					// output if the ImageMagick call was successful
					Console.WriteLine ("[DEBUG-DPI \"" + Path.GetFileName(image) +
					                   "\": " + dpiSuccess.ToString() + "]");
#endif
				}

				// Tell teh user that we will convert all images to one PDF now
				Console.WriteLine ("Merging all jpg files to one PDF...");

				// Temporarily save the output directory path, so we needn't to
				// construct it again and again
				string outDir = WorkingDirectory + Path.DirectorySeparatorChar +
					"Volume " +	manga["volume"] + Path.DirectorySeparatorChar;

				// Create the output directory, if it doesn't already exist
				if(!Directory.Exists(outDir))
					Directory.CreateDirectory(outDir);

				// Call the API function to convert all images to one PDF file
				bool pdfConverted = API.ConvertToPDF(
					subdir,
					outDir + manga["episode"] + " - " + manga["episodeName"] +
					".pdf",
					95);

				// Tell the user where he can find his manga as a PDF file
				// or tell him that something went wrong (depending on what
				// the API call returned us)
				if(pdfConverted)
					Console.WriteLine ("Success! You can find the pdf here:");
				else
					Console.WriteLine ("Sorry, but something went wrong while " +
					 	"converting. But maybe you can find you pdf file " +
					    "nevertheless here:");

				Console.WriteLine (outDir + manga["episode"] + " - " +
				                   manga["episodeName"] + ".pdf");

				// Empty line for nicer output
				Console.WriteLine ();
			}

			// Empty line for nicer output
			Console.WriteLine ();

			// Tell the user that we finished
			Console.WriteLine ("We are finished. Enjoy your mangas as PDF.");
		}

		/// <summary>
		/// Prints the head of our program (copyright, program name, ...).
		/// </summary>
		private static void PrintHead ()
		{
			Console.WriteLine (API.GetProgramName () + " " + 
				API.GetAssemblyVersion ());
			Console.WriteLine (API.GetAssemblyCopyrightNotice ());
			Console.WriteLine ("THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT " +
				"WARRANTY OF ANY KIND");
			Console.WriteLine ();
		}

		/// <summary>
		/// Parses the command-line arguments.
		/// </summary>
		/// <param name='args'>
		/// The command-line arguments.
		/// </param>
		private static void ParseArguments (string[] args)
		{
			foreach (string arg in args) {
				// Clean the arguments (i.e. remove all hyphens, underscores and
				// spaces in front of and behind the arguments)
				string a = arg.Trim ().Trim (new char[] { '-', '_' });

				// Check if the argument is the DPI specification
				// --> We try to use it as the DPI specification
				// -/-> Try other possibilites of argument specifications
				if (a.StartsWith ("dpi=")) {
					// The DPI must be a number, so we check if they are
					// --> Use them as the DPI specification
					// -/-> Do nothing
					int temp;
					if (int.TryParse (a.Substring (4), out temp))
						DPI = a.Substring (4);
				}
				// Check if the argument is a valid folder path
				// --> We use it as our working directory
				// -/-> Do nothing
				else if (Directory.Exists (a)) {
					WorkingDirectory = Path.GetFullPath(a);
					continue;
				}
			}

			// If we have no working directory set until now, we will use the
			// current path where our executable is
			if (String.IsNullOrEmpty (WorkingDirectory))
				WorkingDirectory = Path.GetFullPath(Environment.CurrentDirectory);

			// If we have no DPI specification set until now, we will use 37 as
			// our default specification
			if (String.IsNullOrEmpty (DPI))
				DPI = "37";
		}
	}
}
